//
//  CZPullDownToRefreshControl.swift
//  iOSWeibo10
//
//  Created by itcast on 16/5/18.
//  Copyright © 2016年 itcast. All rights reserved.
//

import UIKit

/// 高度
private let CZPullDownToRefreshControlHeight: CGFloat = 60

/// 定义状态
enum CZPullDownToRefreshStatus {
    case Normal     // 箭头朝下,下拉刷下
    case Pulling    // 箭头朝上,释放刷新
    case Refreshing // 转轮旋转,正在刷新
}

/// 下拉刷新控件
class CZPullDownToRefreshControl: UIView {
    
    // MARK: - 公开方法
    /// 结束刷新的方法
    func endRefreshing() {
        // Refreshing 切换到 Normal 状态
        if currentStatus == .Refreshing {
            currentStatus = .Normal
            
            // 从Refreshing切换到Normal才需要将contentInset设置为原来的值
            UIView.animateWithDuration(CZDefaultDuration, animations: { () -> Void in
                self.superScrollView?.contentInset.top -= CZPullDownToRefreshControlHeight
            })
        }
    }
    
    /// 进入刷新状态
    func beginRefreshing() {
        currentStatus = .Refreshing
    }
    
    // MARK: - 属性
    /// 刷新控件进入刷新状态的闭包
    var pullDownToRefreshCallback: (() -> ())?
    
    /// 记录当前状态
    private var currentStatus: CZPullDownToRefreshStatus = CZPullDownToRefreshStatus.Normal {
        didSet {
            // 状态切换后调用,根据状态设置view的内容
            switch currentStatus {
                case .Normal:
//                    CZPrint(items: "didSet: \(currentStatus),来设置view")
                    // 风火轮停止旋转
                    fhlView.layer.removeAllAnimations()
                    // 隐藏风火轮
                    fhlView.hidden = true
                    // 显示箭头
                    arrowView.hidden = false
                    
                    // 箭头朝下,文字 下拉刷新
                    messageLabel.text = "下拉刷新"
                    UIView.animateWithDuration(CZDefaultDuration, animations: { () -> Void in
                        // 清空transform
                        self.arrowView.transform = CGAffineTransformIdentity
                    })
                
//                    // 从Refreshing切换到Normal才需要将contentInset设置为原来的值
//                    UIView.animateWithDuration(CZDefaultDuration, animations: { () -> Void in
//                        self.superScrollView?.contentInset.top -= CZPullDownToRefreshControlHeight
//                    })
                case .Pulling:
//                    CZPrint(items: "didSet: \(currentStatus),来设置view")
                    // 箭头朝上,文字 释放刷新
                    messageLabel.text = "释放刷新"
                    UIView.animateWithDuration(CZDefaultDuration, animations: { () -> Void in
                        self.arrowView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
                    })
                case .Refreshing:
//                    CZPrint(items: "didSet: \(currentStatus),来设置view")
                    // 隐藏箭头,显示风火轮,文字 正在刷新...
                    self.arrowView.hidden = true
                    self.fhlView.hidden = false
                    self.messageLabel.text = "正在刷新..."
                
                    // 风火轮转起来
                    let rotationAnim = CABasicAnimation(keyPath: "transform.rotation")
                    rotationAnim.toValue = M_PI * 2
                    rotationAnim.duration = CZDefaultDuration * 3
                    rotationAnim.repeatCount = MAXFLOAT
                    rotationAnim.removedOnCompletion = false
                
                    // 开始动画
                    /// 给动画去个名称,下次添加一个动画发现名称一样,先停止之前的动画,在使用刚添加的动画
                    fhlView.layer.addAnimation(rotationAnim, forKey: "rotationAnim")
                
                    // 下拉刷新控件显示出来,修改contentInset.top,在原有的基础上添加下拉刷新控件的高度
                    UIView.animateWithDuration(CZDefaultDuration, animations: { () -> Void in
                        self.superScrollView?.contentInset.top += CZPullDownToRefreshControlHeight
                    })
                
                    // 进入了刷新状态,让别人知道,去加载数据,加载数据完成后需要结束刷新
                    // 调用闭包
                    self.pullDownToRefreshCallback?()
            }
        }
    }
    
    /// 父控件
    private var superScrollView: UIScrollView?
    
    /// Normal和Pulling切换的值
    private var NormalToPullingOffset: CGFloat = -124
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    // 外面创建直接调用[[CZPullDownToRefreshControl alloc] init] -> init(frame: CGRect)
    override init(frame: CGRect) {
        let newFrame = CGRect(x: 0, y: -CZPullDownToRefreshControlHeight, width: UIScreen.mainScreen().bounds.width, height: CZPullDownToRefreshControlHeight)
        super.init(frame: newFrame)
        
        preapreUI()
    }
    
    // 在下拉刷新控件销毁的时候移除监听
    // dealloc
    deinit {
        // 监听谁的属性,就用谁来移除
        superScrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }

    private func preapreUI() {
//        backgroundColor = UIColor.brownColor()
        // 隐藏风火轮
        fhlView.hidden = true
        
        // 添加子控件
        addSubview(arrowView)
        addSubview(fhlView)
        addSubview(messageLabel)
        
        // 添加约束
        /// 箭头
        arrowView.snp_makeConstraints { (make) -> Void in
            make.centerX.equalTo(self).offset(-30)
            make.centerY.equalTo(self)
        }
        
        /// 风火轮和箭头重合
        fhlView.snp_makeConstraints { (make) -> Void in
            make.centerX.centerY.equalTo(arrowView)
        }
        
        /// label
        messageLabel.snp_makeConstraints { (make) -> Void in
            make.leading.equalTo(arrowView.snp_trailing).offset(10)
            make.centerY.equalTo(self)
        }
    }
    
    // 控件监听scrollView的contentOffest.y的改变,监听tableView的属性,在拿到tableView的时候才能去监听,不能再init方法里面监听
    // 下拉刷新控件是添加到了tableView里面.willMoveToSuperview.父控件就是tableView,使用KVO来监听
    override func willMoveToSuperview(newSuperview: UIView?) {
        super.willMoveToSuperview(newSuperview)
        
        if let superScrollView = newSuperview as? UIScrollView {
            // 判断父控件是否是UIScrollView或其子控件
            self.superScrollView = superScrollView
            
            // 监听scrollView的contentOffest
            // observer: NSObject: 谁来监听
            // forKeyPath: 要监听的属性
            // options: 要监听新值,老值
            superScrollView.addObserver(self, forKeyPath: "contentOffset", options: NSKeyValueObservingOptions(rawValue: 0), context: nil)
        }
    }
    
    // KVO监听到了superScrollView的contentOffset的改变
    override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
        // 获取superScrollView的contentOffset.y
//        CZPrint(items: "KVO 监听contentOffset.y: \(superScrollView!.contentOffset.y)")
        /*
        
            用户拖动
                Normal <==> Pulling: 偏移值
            用户松手
                Pulling ==> Refreshing
        
            * 数据加载完了 Refreshing ==> Normal
        */
        if superScrollView!.dragging {
            // 用户正在拖动
            // -120 > -124
            if currentStatus == .Pulling && superScrollView?.contentOffset.y > NormalToPullingOffset {
                // 切换到Normal
                currentStatus = .Normal
//                CZPrint(items: "切换到Normal")
            } else if currentStatus == .Normal && superScrollView?.contentOffset.y < NormalToPullingOffset {
                // -140 < -124
                // 切换到Pulling
                currentStatus = .Pulling
//                CZPrint(items: "切换到,Pulling")
            }
        } else {
            // 用户松手了
            // 判断当前是不是Pulling,当前是Pulling ==> Refreshing
            if currentStatus == .Pulling {
                currentStatus = .Refreshing
//                CZPrint(items: "切换到,Refreshing")
            }
        }
    }
    
    // MARK: - 懒加载
    /// 箭头
    private lazy var arrowView: UIImageView = UIImageView(image: UIImage(named: "tableview_pull_refresh"))
    
    /// 风火轮
    private lazy var fhlView: UIImageView = UIImageView(image: UIImage(named: "tableview_loading"))
    
    /// label
    private lazy var messageLabel: UILabel = {
        let label = UILabel()
        
        // 设置
        label.font = UIFont.systemFontOfSize(14)
        label.textColor = UIColor.darkGrayColor()
        label.text = "下拉刷新"
        label.sizeToFit()
        
        return label
    }()
}
